package com.metel.mservice.common.utils.cookie;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.TimeZone;

import javax.servlet.http.Cookie;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.metel.mservice.common.bean.PropertyBean;

/**
 * CookieHandler
 * 
 * @author sr80.choi
 */
public class CookieHandler {

	private final static Logger logger = LoggerFactory.getLogger(CookieHandler.class);

	public CookieInfo auth(String encryptValue, String timeStamp, String webClientIP) {
		CookieInfo cookieInfo = new CookieInfo();

		String encryptKey = PropertyBean.cookieEncryptKey;
		if (encryptKey == null) {
			logger.info("Cookie EncryptKey is null.");

			return null;
		}

		byte[] bEncryptKey = new byte[16];
		bEncryptKey = encryptKey.getBytes();

		String timeStampKey = timeStamp + timeStamp.charAt(9) + timeStamp.charAt(12);
		byte[] bTimeStamp = new byte[16];
		bTimeStamp = timeStampKey.getBytes();

		byte[] bIV = new byte[16];
		for (int i = 0; i < 16; i++) {
			bIV[i] = (byte) (bEncryptKey[i] ^ bTimeStamp[i]);
		}

		byte[] bEncryptValue = new byte[encryptValue.length() / 2];
		int index = 0;
		for (int i = 0; i < bEncryptValue.length; i++, index = index + 2) {
			bEncryptValue[i] = (byte) Integer.parseInt(encryptValue.substring(index, index + 2), 16);
		}

		byte[] bDecryptValue = GenerateKey.decryptMode(bEncryptKey, bIV, bEncryptValue);

		if (bDecryptValue != null) {
			StringBuffer decryptValue = new StringBuffer();

			for (int i = 0; i < bDecryptValue.length; i++) {
				decryptValue.append((char) bDecryptValue[i]);
			}

			String authValue = decryptValue.toString();
			String tokenDid = "/did=";
			int locDid = authValue.indexOf(tokenDid);
			String tokenIP = "/ip=";
			int locIP = authValue.indexOf(tokenIP);

			String uid = authValue.substring(4, locDid);
			String did = authValue.substring(locDid + 5, locIP);
			String authIP = authValue.substring(locIP + 4);

			Calendar cal = Calendar.getInstance();
			SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
			sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
			cal.setTime(cal.getTime());
			cal.add(Calendar.HOUR_OF_DAY, -1);
			String sDateTime = sdf.format(cal.getTime());
			long lDateTime = Long.parseLong(sDateTime);
			long lTimeStamp = Long.parseLong(timeStamp);

			cookieInfo.setUid(uid);
			cookieInfo.setDid(did);

			if (!webClientIP.equals(authIP)) {
				cookieInfo.setResultCode(7002); // AUTH_INVALID_COOKIE
			} else if (lDateTime > lTimeStamp) {
				cookieInfo.setResultCode(7003); // AUTH_INVALID_COOKIE
			} else {
				cookieInfo.setResultCode(1000);
			}
		} else {
			cookieInfo.setResultCode(7002); // AUTH_INVALID_COOKIE
		}

		return cookieInfo;
	}
	
	public static String[] parseCookie(Cookie[] cookies, String remoteIP) {
		CookieHandler cookieHandler = new CookieHandler();
		String encryptValue = null;
		String timeStamp = null;
		
		if (cookies != null) {
			for (int i = 0; i < cookies.length; i++) {
				Cookie cookie = cookies[i];
				String name = cookie.getName().toLowerCase();

				if (name.equals("encryptvalue")) {
					encryptValue = cookie.getValue();
				} else if (name.equals("timestamp")) {
					timeStamp = cookie.getValue();
				}
			}
		}

		String[] result = null;
		if (encryptValue != null && timeStamp != null) {
			try {
				CookieInfo cookieInfo = cookieHandler.auth(encryptValue, timeStamp, remoteIP);

				int cookieResult = -1;
				if(cookieInfo != null)
				{
					cookieResult = cookieInfo.getResultCode();
				}
				
				switch (cookieResult) {
				case 1000:
					String uid = cookieInfo.getUid();
					String did = cookieInfo.getDid();

					result = new String[] { uid, did };

					logger.debug("[Parsing cookie] get uid: " + uid);
					logger.debug("[Parsing cookie] get imei(did): " + did);

					break;
				case 7002:
					logger.info("[Failed parsing cookie] " + "invalid cookie.");
					break;
				case 7003:
					logger.info("[Failed parsing cookie] " + "expired cookie.");
					break;
				default:
					logger.info("[Failed parsing cookie] " + "encryptValue: " + encryptValue + ", timeStamp: "
							+ timeStamp + ").");
					break;
				}
			} catch (Exception e) {
				logger.info("[Failed parsing cookie] encryptValue: " + encryptValue + " / timeStamp: " + timeStamp + " / remoteIP: " + remoteIP);

				result = null;
			}
		} else {
			if(encryptValue == null) encryptValue = "";
			if(timeStamp == null) timeStamp = "";
			logger.info("[Invalid cookie] encryptValue: " + encryptValue + " / timeStamp: " + timeStamp + " / remoteIP: " + remoteIP);
		}
		cookieHandler = null;
		
		return result;
	}
	
	/**
	 * cookie 생성
	 * 
	 * @param response
	 * @param uid
	 * @param did
	 * @param webClientIP
	 * @return void
	 * @remark N/A
	 * @version 1.0
	 * @author jake.jung 2011. 8. 12. Initial Revision
	 */
	public String cookieMake(String uid, String did, String webClientIP) {

		String encryptKey = PropertyBean.cookieEncryptKey;
		byte[] bEncryptKey = new byte[16];
		bEncryptKey = encryptKey.getBytes();
		// logger.debug("bEncryptKey : {}", bEncryptKey);

		Calendar cal = Calendar.getInstance();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
		sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
		String timeStamp = sdf.format(cal.getTime());
		// logger.debug("timeStamp : {}", timeStamp);

		String timeStampKey = timeStamp + timeStamp.charAt(9) + timeStamp.charAt(12);
		byte[] bTimeStamp = new byte[16];
		bTimeStamp = timeStampKey.getBytes();
		// logger.debug("timeStampKey : {}", timeStampKey);
		// logger.debug("bTimeStamp : {}", bTimeStamp);

		byte[] bIV = new byte[16];
		for (int i = 0; i < 16; i++) {
			bIV[i] = (byte) (bEncryptKey[i] ^ bTimeStamp[i]);
		}
		// logger.debug("bIV : {}", bIV);

		String cookieValue = "uid=" + uid + "/did=" + did + "/ip=" + webClientIP;
		// logger.debug("cookieValue : {}", cookieValue);
		byte[] bCookieValue = new byte[cookieValue.getBytes().length];
		bCookieValue = cookieValue.getBytes();

		// logger.debug("bCookieValue : {}", bCookieValue);

		byte[] bEncryptValue = GenerateKey.encryptMode(bEncryptKey, bIV, bCookieValue);

		StringBuffer resultValue = new StringBuffer();

		if (bEncryptValue != null) {
			for (byte b : bEncryptValue) {
				resultValue.append(Integer.toString((b & 0xF0) >> 4, 16));
				resultValue.append(Integer.toString(b & 0x0F, 16));
			}
		}

		String cookieStr = "EncryptValue=" + resultValue.toString() + "; TimeStamp=" + timeStamp ;
		
		return cookieStr;

	}
}
